#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
AI营销方案生成系统 - 配置管理模块
提供不同环境下的配置管理和环境变量处理

主要功能：
- 基础配置类定义
- 开发/测试/生产环境配置
- 数据库连接配置
- Redis缓存配置
- 火山引擎API配置
- 日志配置
- 安全配置

Author: AI Marketing System
Date: 2024
"""

import os
from datetime import timedelta
from pathlib import Path
from typing import Dict, Any, Optional

# 项目根目录
BASE_DIR = Path(__file__).parent.parent
ROOT_DIR = BASE_DIR.parent


class Config:
    """
    基础配置类
    包含所有环境通用的配置项
    """
    
    # ============= 应用基础配置 =============
    
    # 应用信息
    APP_NAME = "AI营销方案生成系统"
    VERSION = "1.0.0"
    DESCRIPTION = "AI-powered marketing solution generation system"
    
    # 服务器配置
    HOST = os.getenv('HOST', '127.0.0.1')
    PORT = int(os.getenv('PORT', 5000))
    
    # Flask配置
    SECRET_KEY = os.getenv('SECRET_KEY', 'ai-marketing-secret-key-2024')
    JSON_AS_ASCII = False
    JSON_SORT_KEYS = False
    JSONIFY_PRETTYPRINT_REGULAR = True
    
    # 请求配置
    MAX_CONTENT_LENGTH = 16 * 1024 * 1024  # 16MB
    REQUEST_TIMEOUT = 30  # 30秒
    
    # CORS配置
    CORS_ORIGINS = [
        'http://localhost:3000',
        'http://localhost:3001',
        'http://localhost:3002',
        'http://localhost:5173',
        'http://127.0.0.1:3000',
        'http://127.0.0.1:3001',
        'http://127.0.0.1:3002',
        'http://127.0.0.1:5173'
    ]
    
    # ============= 数据库配置 =============
    
    # MongoDB配置
    MONGODB_HOST = os.getenv('MONGODB_HOST', 'localhost')
    MONGODB_PORT = int(os.getenv('MONGODB_PORT', 27017))
    MONGODB_DB = os.getenv('MONGODB_DB', 'ai_marketing')
    MONGODB_USERNAME = os.getenv('MONGODB_USERNAME')
    MONGODB_PASSWORD = os.getenv('MONGODB_PASSWORD')
    MONGODB_AUTH_SOURCE = os.getenv('MONGODB_AUTH_SOURCE', 'admin')
    MONGODB_CONNECT_TIMEOUT = 5000  # 5秒
    MONGODB_SERVER_SELECTION_TIMEOUT = 5000  # 5秒
    MONGODB_MAX_POOL_SIZE = 50
    MONGODB_MIN_POOL_SIZE = 5
    
    @property
    def MONGODB_URI(self) -> str:
        """构建MongoDB连接URI"""
        if self.MONGODB_USERNAME and self.MONGODB_PASSWORD:
            return (
                f"mongodb://{self.MONGODB_USERNAME}:{self.MONGODB_PASSWORD}@"
                f"{self.MONGODB_HOST}:{self.MONGODB_PORT}/{self.MONGODB_DB}"
                f"?authSource={self.MONGODB_AUTH_SOURCE}"
            )
        return f"mongodb://{self.MONGODB_HOST}:{self.MONGODB_PORT}/{self.MONGODB_DB}"
    
    # ============= Redis配置 =============
    
    REDIS_HOST = os.getenv('REDIS_HOST', 'localhost')
    REDIS_PORT = int(os.getenv('REDIS_PORT', 6379))
    REDIS_DB = int(os.getenv('REDIS_DB', 0))
    REDIS_PASSWORD = os.getenv('REDIS_PASSWORD')
    REDIS_DECODE_RESPONSES = True
    REDIS_SOCKET_CONNECT_TIMEOUT = 5
    REDIS_SOCKET_TIMEOUT = 5
    REDIS_CONNECTION_POOL_MAX_CONNECTIONS = 50
    
    # Redis键前缀
    REDIS_KEY_PREFIX = 'ai_marketing:'
    
    # 缓存过期时间（秒）
    CACHE_DEFAULT_TIMEOUT = 3600  # 1小时
    CACHE_USER_SESSION_TIMEOUT = 86400  # 24小时
    CACHE_TEMPLATE_TIMEOUT = 7200  # 2小时
    CACHE_REQUIREMENT_TIMEOUT = 1800  # 30分钟
    
    # ============= 火山引擎配置 =============
    
    # 火山引擎API配置
    VOLCENGINE_ACCESS_KEY = os.getenv('VOLCENGINE_ACCESS_KEY')
    VOLCENGINE_SECRET_KEY = os.getenv('VOLCENGINE_SECRET_KEY')
    VOLCENGINE_REGION = os.getenv('VOLCENGINE_REGION', 'cn-beijing')
    
    # ARK模型配置
    ARK_API_KEY = os.getenv('ARK_API_KEY')
    ARK_BASE_URL = os.getenv('ARK_BASE_URL', 'https://ark.cn-beijing.volces.com/api/v3')
    ARK_MODEL_ID = os.getenv('ARK_MODEL_ID', '')  # 端点ID，需要在火山引擎控制台创建推理接入点后获得
    ARK_MAX_TOKENS = int(os.getenv('ARK_MAX_TOKENS', 4000))
    ARK_TEMPERATURE = float(os.getenv('ARK_TEMPERATURE', 0.7))
    ARK_TOP_P = float(os.getenv('ARK_TOP_P', 0.9))
    ARK_TIMEOUT = int(os.getenv('ARK_TIMEOUT', 60))
    
    # ============= JWT配置 =============
    
    JWT_SECRET_KEY = os.getenv('JWT_SECRET_KEY', SECRET_KEY)
    JWT_ACCESS_TOKEN_EXPIRES = timedelta(
        hours=int(os.getenv('JWT_ACCESS_TOKEN_EXPIRES_HOURS', 24))
    )
    JWT_REFRESH_TOKEN_EXPIRES = timedelta(
        days=int(os.getenv('JWT_REFRESH_TOKEN_EXPIRES_DAYS', 30))
    )
    JWT_ALGORITHM = 'HS256'
    
    # ============= 限流配置 =============
    
    # 全局限流
    RATE_LIMIT_GLOBAL = os.getenv('RATE_LIMIT_GLOBAL', '1000/hour')
    
    # API限流
    RATE_LIMIT_API_DEFAULT = os.getenv('RATE_LIMIT_API_DEFAULT', '100/minute')
    RATE_LIMIT_API_AUTH = os.getenv('RATE_LIMIT_API_AUTH', '10/minute')
    RATE_LIMIT_API_CHAT = os.getenv('RATE_LIMIT_API_CHAT', '20/minute')
    RATE_LIMIT_API_GENERATE = os.getenv('RATE_LIMIT_API_GENERATE', '5/minute')
    
    # ============= 文件上传配置 =============
    
    UPLOAD_FOLDER = BASE_DIR / 'uploads'
    ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif', 'doc', 'docx'}
    MAX_FILE_SIZE = 10 * 1024 * 1024  # 10MB
    
    # ============= 日志配置 =============
    
    LOG_LEVEL = os.getenv('LOG_LEVEL', 'INFO')
    LOG_FORMAT = (
        '%(asctime)s - %(name)s - %(levelname)s - '
        '[%(filename)s:%(lineno)d] - %(message)s'
    )
    LOG_DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
    
    # 日志文件配置
    LOG_DIR = BASE_DIR / 'logs'
    LOG_FILE_MAX_SIZE = 10 * 1024 * 1024  # 10MB
    LOG_FILE_BACKUP_COUNT = 5
    
    # ============= 业务配置 =============
    
    # 模板配置
    TEMPLATE_MAX_COUNT = 1000  # 最大模板数量
    TEMPLATE_CACHE_TIMEOUT = 3600  # 模板缓存时间
    
    # 需求配置
    REQUIREMENT_MAX_LENGTH = 10000  # 需求描述最大长度
    REQUIREMENT_BATCH_SIZE = 50  # 批量处理大小
    
    # 聊天配置
    CHAT_MAX_HISTORY = 100  # 最大聊天历史数量
    CHAT_SESSION_TIMEOUT = 3600  # 聊天会话超时时间
    
    # 生成配置
    GENERATION_TIMEOUT = 120  # 生成超时时间
    GENERATION_MAX_RETRY = 3  # 最大重试次数
    
    # ============= 安全配置 =============
    
    # 密码配置
    PASSWORD_MIN_LENGTH = 8
    PASSWORD_REQUIRE_UPPERCASE = True
    PASSWORD_REQUIRE_LOWERCASE = True
    PASSWORD_REQUIRE_DIGIT = True
    PASSWORD_REQUIRE_SPECIAL = False
    
    # 会话配置
    SESSION_TIMEOUT = 86400  # 24小时
    SESSION_REFRESH_THRESHOLD = 3600  # 1小时
    
    # IP白名单（开发环境可为空）
    IP_WHITELIST = os.getenv('IP_WHITELIST', '').split(',') if os.getenv('IP_WHITELIST') else []
    
    @staticmethod
    def init_app(app):
        """初始化应用配置"""
        # 创建必要的目录
        Config.UPLOAD_FOLDER.mkdir(exist_ok=True)
        Config.LOG_DIR.mkdir(exist_ok=True)
    
    @classmethod
    def get_config(cls, config_name: str) -> 'Config':
        """根据配置名称获取配置类"""
        config_map = {
            'development': DevelopmentConfig,
            'testing': TestingConfig,
            'production': ProductionConfig,
            'default': DevelopmentConfig
        }
        return config_map.get(config_name, config_map['default'])


class DevelopmentConfig(Config):
    """
    开发环境配置
    """
    
    ENV = 'development'
    DEBUG = True
    TESTING = False
    
    # 开发环境数据库
    MONGODB_DB = os.getenv('MONGODB_DB', 'ai_marketing_dev')
    REDIS_DB = int(os.getenv('REDIS_DB', 0))
    
    # 开发环境日志
    LOG_LEVEL = 'DEBUG'
    
    # 开发环境CORS（允许开发端口）
    CORS_ORIGINS = [
        'http://localhost:3000',
        'http://localhost:3001',
        'http://localhost:5173',
        'http://127.0.0.1:3000',
        'http://127.0.0.1:3001',
        'http://127.0.0.1:5173'
    ]
    
    # 开发环境限流（更宽松）
    RATE_LIMIT_GLOBAL = '10000/hour'
    RATE_LIMIT_API_DEFAULT = '1000/minute'
    RATE_LIMIT_API_CHAT = '100/minute'
    RATE_LIMIT_API_GENERATE = '50/minute'
    
    # 开发环境缓存（较短过期时间）
    CACHE_DEFAULT_TIMEOUT = 300  # 5分钟
    CACHE_TEMPLATE_TIMEOUT = 600  # 10分钟
    
    @staticmethod
    def init_app(app):
        Config.init_app(app)
        
        # 开发环境特定初始化
        print("🔧 开发环境配置已加载")
        print(f"📊 MongoDB: {app.config['MONGODB_URI']}")
        print(f"🔴 Redis: {app.config['REDIS_HOST']}:{app.config['REDIS_PORT']}/{app.config['REDIS_DB']}")


class TestingConfig(Config):
    """
    测试环境配置
    """
    
    ENV = 'testing'
    DEBUG = True
    TESTING = True
    
    # 测试环境数据库
    MONGODB_DB = os.getenv('MONGODB_DB', 'ai_marketing_test')
    REDIS_DB = int(os.getenv('REDIS_DB', 1))
    
    # 测试环境日志
    LOG_LEVEL = 'WARNING'
    
    # 测试环境JWT（较短过期时间）
    JWT_ACCESS_TOKEN_EXPIRES = timedelta(minutes=15)
    JWT_REFRESH_TOKEN_EXPIRES = timedelta(hours=1)
    
    # 测试环境缓存（很短过期时间）
    CACHE_DEFAULT_TIMEOUT = 60  # 1分钟
    CACHE_TEMPLATE_TIMEOUT = 120  # 2分钟
    
    @staticmethod
    def init_app(app):
        Config.init_app(app)
        print("🧪 测试环境配置已加载")


class ProductionConfig(Config):
    """
    生产环境配置
    """
    
    ENV = 'production'
    DEBUG = False
    TESTING = False
    
    # 生产环境环境变量（在init_app中验证）
    SECRET_KEY = os.getenv('SECRET_KEY')
    JWT_SECRET_KEY = os.getenv('JWT_SECRET_KEY')
    
    # 生产环境数据库
    MONGODB_DB = os.getenv('MONGODB_DB', 'ai_marketing_prod')
    REDIS_DB = int(os.getenv('REDIS_DB', 2))
    
    # 生产环境日志
    LOG_LEVEL = 'WARNING'
    
    # 生产环境CORS（严格限制）
    CORS_ORIGINS = [
        'https://ai-marketing.example.com',
        'https://www.ai-marketing.example.com'
    ]
    
    # 生产环境限流（严格限制）
    RATE_LIMIT_GLOBAL = '500/hour'
    RATE_LIMIT_API_DEFAULT = '50/minute'
    RATE_LIMIT_API_CHAT = '10/minute'
    RATE_LIMIT_API_GENERATE = '3/minute'
    
    # 生产环境安全配置
    SESSION_COOKIE_SECURE = True
    SESSION_COOKIE_HTTPONLY = True
    SESSION_COOKIE_SAMESITE = 'Lax'
    
    @staticmethod
    def init_app(app):
        Config.init_app(app)
        
        # 验证生产环境必需的环境变量
        if not app.config.get('SECRET_KEY'):
            raise ValueError("生产环境必须设置SECRET_KEY环境变量")
        
        if not app.config.get('JWT_SECRET_KEY'):
            raise ValueError("生产环境必须设置JWT_SECRET_KEY环境变量")
        
        # 生产环境特定初始化
        import logging
        from logging.handlers import RotatingFileHandler
        
        # 配置文件日志
        if not app.debug:
            file_handler = RotatingFileHandler(
                Config.LOG_DIR / 'ai_marketing.log',
                maxBytes=Config.LOG_FILE_MAX_SIZE,
                backupCount=Config.LOG_FILE_BACKUP_COUNT
            )
            file_handler.setFormatter(logging.Formatter(
                Config.LOG_FORMAT
            ))
            file_handler.setLevel(logging.WARNING)
            app.logger.addHandler(file_handler)
        
        print("🚀 生产环境配置已加载")


# 配置映射
config = {
    'development': DevelopmentConfig,
    'testing': TestingConfig,
    'production': ProductionConfig,
    'default': DevelopmentConfig
}


def get_config_by_name(config_name: Optional[str] = None) -> Config:
    """
    根据配置名称获取配置实例
    
    Args:
        config_name (str, optional): 配置名称
        
    Returns:
        Config: 配置实例
    """
    if config_name is None:
        config_name = os.getenv('FLASK_ENV', 'development')
    
    return config.get(config_name, config['default'])


def validate_config(config_obj: Config) -> Dict[str, Any]:
    """
    验证配置的有效性
    
    Args:
        config_obj (Config): 配置对象
        
    Returns:
        Dict[str, Any]: 验证结果
    """
    errors = []
    warnings = []
    
    # 检查必需的配置项
    required_configs = [
        'SECRET_KEY',
        'MONGODB_HOST',
        'REDIS_HOST'
    ]
    
    for config_name in required_configs:
        if not getattr(config_obj, config_name, None):
            errors.append(f"缺少必需的配置项: {config_name}")
    
    # 检查火山引擎配置
    if not config_obj.ARK_API_KEY:
        warnings.append("未配置火山引擎ARK_API_KEY，AI功能将不可用")
    
    # 检查生产环境特殊要求
    if config_obj.ENV == 'production':
        if config_obj.DEBUG:
            errors.append("生产环境不应启用DEBUG模式")
        
        if not config_obj.MONGODB_USERNAME or not config_obj.MONGODB_PASSWORD:
            warnings.append("生产环境建议配置MongoDB认证")
        
        if not config_obj.REDIS_PASSWORD:
            warnings.append("生产环境建议配置Redis密码")
    
    return {
        'valid': len(errors) == 0,
        'errors': errors,
        'warnings': warnings
    }